<?php
class SSHAgent {
	static protected $SSH_POOL;
	
	private $host;
	private $port;
	private $user;
	private $poolKey;
	
	private $publicKey;
	private $privateKey;
	private $passphrase;
	
	CONST TTL_LIMIT = 300;

	protected function getSSH() {
		if (self::$SSH_POOL[$this->poolKey]['ttl'] < time()) {
			$this->connect();
		}
		
		return self::$SSH_POOL[$this->poolKey]['ssh'];
	}
	
	protected function getSFTP() {
		if (self::$SSH_POOL[$this->poolKey]['ttl'] < time()) {
			$this->connect();
		}
		
		return self::$SSH_POOL[$this->poolKey]['sftp'];
	}
	
	protected function connect() {
		$ssh = ssh2_connect($this->host, $this->port);
		if ($ssh === FALSE) {
			error_log("Connect Fails: {$this->host}");
			throw new Exception("Connect Fails: {$this->host}");
		}
		
		$ret = ssh2_auth_pubkey_file($ssh, $this->user, $this->publicKey, $this->privateKey, $this->passphrase);
		if ($ret === FALSE) {
			error_log("Auth Fails: {$this->host}");
			throw new Exception("Auth Fails: {$this->host}");
		}
		
		self::$SSH_POOL[$this->poolKey]['ssh'] = $ssh;
		self::$SSH_POOL[$this->poolKey]['sftp'] = ssh2_sftp($ssh);
		self::$SSH_POOL[$this->poolKey]['ttl'] = time() + self::TTL_LIMIT;
	}
	
	public function __construct($host, $port, $user, $publicKey, $privateKey, $passphrase) {
		$this->host = $host;
		$this->port = $port;
		$this->user = $user;
		$this->poolKey = "{$this->host}-{$this->port}-{$this->user}";		
		$this->publicKey = $publicKey;
		$this->privateKey = $privateKey;
		$this->passphrase = $passphrase;
		$this->connect();
	}
	
	
	protected function remoteExec($cmd) {
		$stream = ssh2_exec($this->getSSH(), $cmd);
		stream_set_blocking($stream, true);
		$ret = '';
		while ($line = fgets($stream)) {
			flush();
			$ret .= $line;
		}
		
		return $ret;
	}
	
	public function recursiveMkdir($dir, $mode) {
		$sftp = $this->getSFTP();
		if (file_exists("ssh2.sftp://{$sftp}{$dir}")) {
			return TRUE;
		}

		$ret = mkdir("ssh2.sftp://{$sftp}{$dir}", 0777, TRUE);
		
		return $ret;
	}

	public function sendFile($localFile, $remoteFile) {
		$dir = dirname($remoteFile);
		$ret = $this->recursiveMkdir($dir, 0777);
		
		$sftp = $this->getSFTP();
		$data = file_get_contents($localFile);
		$ret = file_put_contents("ssh2.sftp://{$sftp}{$remoteFile}", $data);

		if ($ret === FALSE) {
			error_log("Cannot copy {$localFile} to {$this->host}:{$remoteFile}");
			return FALSE;
		}
	
		return TRUE;
		
	}
	
	public function receiveFile($remoteFile, $localFile) {
		$dir = dirname($localFile);
		$ret = @mkdir($dir, 0777, TRUE);
		$ret = @chmod($dir, 0777);
		
		$sftp = $this->getSFTP();      
		$contents = file_get_contents ("ssh2.sftp://{$sftp}{$remoteFile}");
		$ret = file_put_contents($localFile, $contents);
        
		if ($ret === FALSE) {
			error_log("Cannot copy to {$this->host}:{$remoteFile} to {$localFile}");
			return FALSE;
		}
		
		return TRUE;
	}
	
	public function removeFile($destFile) {
		$sftp = $this->getSFTP();
		$ret = unlink("ssh2.sftp://{$sftp}{$destFile}");
		if ($ret === FALSE) {
			error_log("Cannot remove {$this->host}:{$destFile}");
			return FALSE;
		}
		
		return TRUE;
	}
	
	public function removeDir($dir) {
		$sftp = $this->getSFTP();
		$ret = rmdir("ssh2.sftp://{$sftp}{$dir}");
		if ($ret === FALSE) {
			error_log("Cannot remove {$this->host}:{$dir}");
			return FALSE;
		}
		
		return TRUE;
	}
}
?>
